﻿using System.Linq;
using Brjnk.Common;
using Brjnk.Common.Extensions;
using Brjnk.GpxExplorer.ViewModel;

namespace Brjnk.GpxExplorer.Workspace.Searching
{
    public class PushpinsManager
    {
        private SearchService service;

        private bool allowMoreThanOnePushpin;

        public PushpinsManager(SearchService service)
        {
            this.service = service;
            App.Instance.Settings.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(Settings_PropertyChanged);
            Refresh();
            CreateCommands();
        }

        private void Settings_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            if (e.PropertyName == "AllowMoreThanOnePushpin") Refresh();
        }

        private DataView GetDataView()
        {
            return App.Instance.Workspace.DataView;
        }

        public void RemovePushpins()
        {
            service.SearchedItems.RemoveWhere(o => o is Pushpin);
        }

        public void AddPushpin(GpsCoordinates coordinates, string text)
        {
            if (!allowMoreThanOnePushpin) RemovePushpins();
            AddPushpin(new Pushpin(coordinates, text));
        }

        public void AddPushpin(IPoint point)
        {
            if (!allowMoreThanOnePushpin) RemovePushpins();
            AddPushpin(new Pushpin(point));
        }

        private void AddPushpin(Pushpin p)
        {
            p.MaxDistance = searchArgsConfiguration.MaxPushpinDistance;
            p.ShowAgainDistance = searchArgsConfiguration.SearchAgainPushpinDistance;
            p.SearchInGaps = searchArgsConfiguration.SearchPhotosInPathGaps;
            service.SearchedItems.Add(p);
        }

        public void AddPushpinAndGo(GpsCoordinates coordinates, string text, bool useBigZoom)
        {
            AddPushpin(coordinates, text);
            GetDataView().GoToPoint(coordinates, useBigZoom);
        }

        public void AddPushpinAndGo(IPoint point, bool useBigZoom)
        {
            AddPushpin(point);
            GetDataView().GoToPoint(point.PositionI, useBigZoom);
        }

        public int GetPushpinsCount()
        {
            return service.SearchedItems.Where(i => i is Pushpin).Count();
        }

        private SearchConfiguration searchArgsConfiguration;

        public void Refresh()
        {
            searchArgsConfiguration = App.Instance.Settings.SearchConfiguration;
            allowMoreThanOnePushpin = App.Instance.Settings.AllowMoreThanOnePushpin;
            int count = 0;

            for (int i = 0; i < service.SearchedItems.Count; i++)
            {
                var item = service.SearchedItems[i] as Pushpin;
                if ((object)item == null) continue;
                count++;
                item.SearchInGaps = searchArgsConfiguration.SearchPushpinsInPathGaps;
                item.MaxDistance = searchArgsConfiguration.MaxPushpinDistance;
                item.ShowAgainDistance = searchArgsConfiguration.SearchAgainPushpinDistance;
            }
            if (count > 1 && allowMoreThanOnePushpin == false)
            {
                var toRemove = service.SearchedItems.Where(i => i is Pushpin).ToList();
                toRemove.Remove(toRemove.Last());
                for (int i = 0; i < toRemove.Count; i++)
                    service.SearchedItems.Remove(toRemove[i]);
            }
        }

        # region Commands

        private void CreateCommands()
        {
            AddPushpinCommand = new GenericCommand(AddPushpinCommandMethod);
            AddPushpinAndGoCommand = new GenericCommand(AddPushpinAndGoCommandMethod);
            AddPushpinAndGoBigZoomCommand = new GenericCommand(AddPushpinAndGoBigZoomCommandMethod);
            RemovePushpinsCommand = new GenericCommand(o => RemovePushpins());
        }

        private void AddPushpinCommandMethod(object arg)
        {
            if (arg is IPoint)
                AddPushpin(arg as IPoint);
            else if (arg is GpsCoordinates)
                AddPushpin((GpsCoordinates)arg, string.Empty);
            else
                System.Diagnostics.Debug.WriteLine("PushpinsManager: Unknow parameter");
        }

        private void AddPushpinAndGoCommandMethod(object arg)
        {
            if (arg is IPoint)
                AddPushpinAndGo(arg as IPoint, false);
            else if (arg is GpsCoordinates)
                AddPushpinAndGo((GpsCoordinates)arg, string.Empty, false);
            else
                System.Diagnostics.Debug.WriteLine("PushpinsManager: Unknow parameter");
        }

        private void AddPushpinAndGoBigZoomCommandMethod(object arg)
        {
            if (arg is IPoint)
                AddPushpinAndGo(arg as IPoint, true);
            else if (arg is GpsCoordinates)
                AddPushpinAndGo((GpsCoordinates)arg, string.Empty, true);
            else
                System.Diagnostics.Debug.WriteLine("PushpinsManager: Unknow parameter");
        }

        public GenericCommand AddPushpinCommand { get; private set; }

        public GenericCommand AddPushpinAndGoCommand { get; private set; }

        public GenericCommand AddPushpinAndGoBigZoomCommand { get; private set; }

        public GenericCommand RemovePushpinsCommand { get; private set; }

        # endregion
    }
}